package com.qdc.datacenters.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.pagehelper.PageInfo;
import com.qdc.datacenters.config.security.QdcGrantedAuthority;
import com.qdc.datacenters.domain.LoginUserInfo;
import com.qdc.datacenters.domain.entity.BaseEntity;
import com.qdc.datacenters.domain.entity.SysUser;
import com.qdc.datacenters.domain.entity.SysUserDept;
import com.qdc.datacenters.domain.entity.SysUserRole;
import com.qdc.datacenters.domain.feature.IUserVo;
import com.qdc.datacenters.domain.query.BaseQuery;
import com.qdc.datacenters.domain.query.user.SysUserAddQuery;
import com.qdc.datacenters.domain.query.user.SysUserQuery;
import com.qdc.datacenters.domain.query.user.SysUserUpdateQuery;
import com.qdc.datacenters.domain.vo.dept.SysDeptVo;
import com.qdc.datacenters.domain.vo.menu.SysMenuVo;
import com.qdc.datacenters.domain.vo.role.SysRoleVo;
import com.qdc.datacenters.domain.vo.user.SysSimpleUserVo;
import com.qdc.datacenters.domain.vo.user.SysUserVo;
import com.qdc.datacenters.enums.DeleteStatusEnum;
import com.qdc.datacenters.enums.ExceptionStatusEnum;
import com.qdc.datacenters.exception.CommonException;
import com.qdc.datacenters.mapper.SysUserMapper;
import com.qdc.datacenters.service.*;
import com.qdc.datacenters.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户信息表(User)表服务实现类
 *
 * @author danmo
 * @since 2024-02-20 18:41:33
 */
@Slf4j
@Service
public class SysSysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Autowired
    private ISysRoleService iSysRoleService;

    @Autowired
    private ISysDeptService iSysDeptService;

    @Autowired
    private ISysUserRoleService iSysUserRoleService;

    @Autowired
    private ISysUserDeptService iSysUserDeptService;

    @Override
    public SysUser getByUsername(String username) {
        return getOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUserName, username).eq(BaseEntity::getDelFlag, 0));
    }

    @Override
    public SysUser getByCorpUserId(String corpUserId) {
        return getOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getCorpUserId, corpUserId).eq(BaseEntity::getDelFlag, 0));
    }

    @Override
    public LoginUserInfo loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = getByUsername(username);
        if (Objects.isNull(sysUser)) {
            throw new UsernameNotFoundException("用户不存在！");
        }

        LoginUserInfo loginUserInfo = new LoginUserInfo();
        loginUserInfo.setUserId(sysUser.getUserId());
        loginUserInfo.setUsername(sysUser.getUserName());
        loginUserInfo.setNickName(sysUser.getNickName());
        loginUserInfo.setPassword(sysUser.getPassword());
        loginUserInfo.setAvatar(sysUser.getAvatar());
        loginUserInfo.setSex(sysUser.getSex());
        loginUserInfo.setPhone(sysUser.getPhone());

        if (Objects.equals(1, sysUser.getStatus())) {
            loginUserInfo.setEnabled(true);
        }
        List<SysDeptVo> deptVos = iSysDeptService.getDeptByUserId(sysUser.getUserId());
        loginUserInfo.setDeptInfo(deptVos);
        List<SysRoleVo> roleList = iSysRoleService.getRoleByUserId(sysUser.getUserId());
        List<Long> roleIds = Optional.ofNullable(roleList).orElseGet(ArrayList::new).stream()
                .filter(role -> Objects.equals(0, role.getStatus())).map(SysRoleVo::getRoleId).collect(Collectors.toList());
        loginUserInfo.setRoleIds(roleIds);

        Set<Integer> dataScopes = Optional.ofNullable(roleList).orElseGet(ArrayList::new).stream()
                .filter(role -> Objects.equals(0, role.getStatus())).map(SysRoleVo::getDataScope).collect(Collectors.toSet());
        loginUserInfo.setDataScope(new ArrayList<>(dataScopes));

        Set<QdcGrantedAuthority> authorities = Optional.ofNullable(roleList).orElseGet(ArrayList::new).stream()
                .filter(role -> Objects.equals(0, role.getStatus())).map(role -> new QdcGrantedAuthority(role.getRoleKey(), role.getMenuList().stream().map(SysMenuVo::getPerms).filter(StringUtils::isNotBlank).collect(Collectors.toList()))).collect(Collectors.toSet());
        loginUserInfo.setAuthorities(authorities);

        loginUserInfo.setAccountNonExpired(true);
        loginUserInfo.setCredentialsNonExpired(true);
        loginUserInfo.setAccountNonLocked(true);
        return loginUserInfo;
    }

    @Override
    public SysUserVo getByUserId(Long userId) {
        return this.baseMapper.getByUserId(userId);
    }


    @Override
    public PageInfo<SysUserVo> getPageList(SysUserQuery query) {
        List<SysUserVo> userList = new LinkedList<>();
        List<Long> userIds = this.baseMapper.selectUserIdsByQuery(query);
        if (!CollectionUtils.isEmpty(userIds)) {
            query.setUserIds(userIds);
            startPage(query.getPageIndex(), query.getPageSize(), query.getSortField(), query.getSort());
            List<SysUserVo> pageList = this.baseMapper.getPageList(query);
            userList.addAll(pageList);
        }
        decorate(userList);
        PageInfo<Long> pageTempInfo = new PageInfo<>(userIds);
        PageInfo<SysUserVo> pageInfo = new PageInfo<>(userList);
        pageInfo.setTotal(pageTempInfo.getTotal());
        pageInfo.setPageNum(pageTempInfo.getPageNum());
        pageInfo.setPageSize(pageTempInfo.getPageSize());
        return pageInfo;
    }

    @Override
    public List<SysUserVo> getList(SysUserQuery query) {
        return this.baseMapper.getList(query);
    }

    @Override
    public void decorate(IUserVo userVo) {
        if (Objects.isNull(userVo)) {
            return;
        }
        if (userVo.getCreateBy() == null && userVo.getUpdateBy() == null) {
            return;
        }
        Set<Long> userIds = new HashSet<>();
        userIds.add(userVo.getCreateBy());
        userIds.add(userVo.getUpdateBy());
        SysUserQuery query = new SysUserQuery();
        query.setUserIds(new ArrayList<>(userIds));

        List<SysUserVo> userList = getList(query);
        if (CollectionUtils.isEmpty(userList)) {
            return;
        }
        Map<Long, String> userMap = userList.stream().collect(Collectors.toMap(SysUserVo::getUserId, SysUserVo::getNickName, (key1, key2) -> key1));
        userVo.setCreateName(userMap.get(userVo.getCreateBy()));
        userVo.setUpdateName(userMap.get(userVo.getUpdateBy()));
    }

    @Override
    public void decorate(List<? extends IUserVo> userVoList) {
        if (CollectionUtils.isEmpty(userVoList)) {
            return;
        }
        Set<Long> userIds = new HashSet<>();
        for (IUserVo userVo : userVoList) {
            if (userVo.getCreateBy() == null && userVo.getUpdateBy() == null) {
                continue;
            }
            userIds.add(userVo.getCreateBy());
            userIds.add(userVo.getUpdateBy());
        }
        List<Long> userIdList = userIds.stream().filter(Objects::nonNull).toList();
        SysUserQuery query = new SysUserQuery();
        query.setUserIds(new ArrayList<>(userIdList));
        List<SysUserVo> userList = getList(query);
        if (CollectionUtils.isEmpty(userList)) {
            return;
        }
        Map<Long, String> userMap = userList.stream().collect(Collectors.toMap(SysUserVo::getUserId, SysUserVo::getNickName, (key1, key2) -> key1));
        for (IUserVo userVo : userVoList) {
            userVo.setCreateName(userMap.get(userVo.getCreateBy()));
            userVo.setUpdateName(userMap.get(userVo.getUpdateBy()));
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(SysUserAddQuery query) {
        //校验用户名称
        SysUserQuery userQuery = new SysUserQuery();
        userQuery.setUserName(query.getUserName());
        userQuery.setCorpUserId(query.getCorpUserId());
        if (checkUserName(userQuery)) {
            throw new CommonException(ExceptionStatusEnum.ERROR_USER_NAME_EXISTENCE.getCode(), ExceptionStatusEnum.ERROR_USER_NAME_EXISTENCE.getMsg());
        }
        if (checkCorpUserId(userQuery)) {
            throw new CommonException(ExceptionStatusEnum.ERROR_CORP_USER_ID_EXISTENCE.getCode(), ExceptionStatusEnum.ERROR_CORP_USER_ID_EXISTENCE.getMsg());
        }
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(query, sysUser);
        if (save(sysUser)) {
            if (!CollectionUtils.isEmpty(query.getRoleIds())) {
                List<SysUserRole> sysUserRoles = query.getRoleIds().stream().map(roleId -> {
                    SysUserRole sysUserRole = new SysUserRole();
                    sysUserRole.setUserId(sysUser.getUserId());
                    sysUserRole.setRoleId(roleId);
                    return sysUserRole;
                }).collect(Collectors.toList());
                iSysUserRoleService.saveBatch(sysUserRoles);
            }

            if (!CollectionUtils.isEmpty(query.getDeptIds())) {
                List<SysUserDept> sysUserDepts = query.getDeptIds().stream().map(deptId -> {
                    SysUserDept sysUserDept = new SysUserDept();
                    sysUserDept.setUserId(sysUser.getUserId());
                    sysUserDept.setDeptId(deptId);
                    return sysUserDept;
                }).collect(Collectors.toList());
                iSysUserDeptService.saveBatch(sysUserDepts);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(SysUserUpdateQuery query) {
        //校验用户名称
        SysUserQuery userQuery = new SysUserQuery();
        userQuery.setUserName(query.getUserName());
        userQuery.setCorpUserId(query.getCorpUserId());
        if (checkUserName(userQuery)) {
            throw new CommonException(ExceptionStatusEnum.ERROR_USER_NAME_EXISTENCE.getCode(), ExceptionStatusEnum.ERROR_USER_NAME_EXISTENCE.getMsg());
        }
        if (checkCorpUserId(userQuery)) {
            throw new CommonException(ExceptionStatusEnum.ERROR_CORP_USER_ID_EXISTENCE.getCode(), ExceptionStatusEnum.ERROR_CORP_USER_ID_EXISTENCE.getMsg());
        }

        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(query, sysUser);
        sysUser.setUserId(query.getUserId());
        if (updateById(sysUser)) {
            if (!CollectionUtils.isEmpty(query.getRoleIds())) {
                iSysUserRoleService.updateBatch(query.getUserId(), query.getRoleIds());
            }
            if (!CollectionUtils.isEmpty(query.getDeptIds())) {
                iSysUserDeptService.updateBatch(query.getUserId(), query.getDeptIds());
            }
        }
    }


    @Override
    public void editPassWord(SysUserAddQuery query) {
        if (StringUtils.isEmpty(query.getPassword())) {
            throw new CommonException("密码不能为空");
        }
        update(new LambdaUpdateWrapper<SysUser>()
                .set(SysUser::getPassword, SecurityUtils.encryptPassword(query.getPassword()))
                .eq(SysUser::getUserId, query.getUserId()));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(SysUserQuery query) {
        if (!CollectionUtils.isEmpty(query.getUserIds())) {
            List<SysUser> userList = query.getUserIds().stream().map(userId -> {
                SysUser lfsUser = new SysUser();
                lfsUser.setDelFlag(1);
                lfsUser.setUserId(userId);
                return lfsUser;
            }).collect(Collectors.toList());

            boolean update = updateBatchById(userList);
            if (update) {
                iSysUserRoleService.update(new LambdaUpdateWrapper<SysUserRole>().set(BaseEntity::getDelFlag, DeleteStatusEnum.DELETE_YES.getIndex()).in(SysUserRole::getUserId, query.getUserIds()));
                iSysUserDeptService.update(new LambdaUpdateWrapper<SysUserDept>().set(BaseEntity::getDelFlag, DeleteStatusEnum.DELETE_YES.getIndex()).in(SysUserDept::getUserId, query.getUserIds()));
            }
        }
    }

    @Override
    public List<SysSimpleUserVo> getCorpUserList(BaseQuery query) {
        return this.baseMapper.getCorpUserList(query);
    }

    private boolean checkUserName(SysUserQuery query) {
        if (StringUtils.isNotEmpty(query.getUserName())) {
            SysUser sysUser = getByUsername(query.getUserName());
            if (Objects.nonNull(sysUser)) {
                return true;
            }
        }
        return false;
    }

    private boolean checkCorpUserId(SysUserQuery query) {
        if (StringUtils.isNotEmpty(query.getCorpUserId())) {
            SysUser sysUser = getByCorpUserId(query.getCorpUserId());
            if (Objects.nonNull(sysUser)) {
                return true;
            }
        }
        return false;
    }

}

